/**
 *
 * \file CDefaultEventHandler.cpp
 * \brief This file contains the CDefaultEventHandler class implementation.
 * \author Vladimir Klubkov (aka marked)
 *
 * Last changes date:
 * \date 15.03.2011
 *
 * Copyright 2011 Vladimir Klubkov <marked-one@yandex.ru>
 *
 * This file is part of OOXlib.
 *
 * OOXLib is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * OOXlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OOXlib; if not, you can try to find  it here:
 * http://www.gnu.org/licenses/gpl.txt
 * or write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "../include/CDefaultEventHandler.h"

namespace OOXlib {

/**
 * Constructor.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 */
CDefaultEventHandler::CDefaultEventHandler(const CXServerConnection *pXServerConnection)
: m_pXServerConnection(pXServerConnection) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
}
/**
 * Event handler.
 * \param Event XEvent structure.
 * \param pWindow Window object.
 * \return False if needed to exit, else - true.
 */
bool CDefaultEventHandler::HandleEvents(::XEvent &Event, IWindow *pWindow) const {
    if(NULL == pWindow) {
        return false;
    }
    switch(Event.type) {
        case Expose: {
            pWindow->OnExpose();
            break;
        } case ButtonPress: {
            pWindow->OnButtonPress(Event.xbutton.button, Event.xbutton.x, Event.xbutton.y);
            break;
        } case ButtonRelease: {
            pWindow->OnButtonRelease(Event.xbutton.button, Event.xbutton.x, Event.xbutton.y);
            break;
        } case EnterNotify: {
            pWindow->OnMouseEnter(Event.xcrossing.x, Event.xcrossing.y);
            break;
        } case LeaveNotify: {
            pWindow->OnMouseExit(Event.xcrossing.x, Event.xcrossing.y);
            break;
        } case MotionNotify: {
            pWindow->OnMouseMove(Event.xmotion.x, Event.xmotion.y);
            break;
        } case FocusIn: {
            pWindow->OnGotFocus();
            break;
        } case FocusOut: {
            pWindow->OnLostFocus();
            break;
        } case KeyPress:
        case KeyRelease: {
            char buffer[256];
            ::KeySym keysym;
            ::XComposeStatus status;
            // Become the KeySym from event.
            int count = ::XLookupString(&Event.xkey, buffer, 255, &keysym, &status);
            buffer[count] = 0;
            if(KeyPress == Event.type) {
                pWindow->OnKeyPress(keysym);
            } else if(KeyRelease == Event.type) {
                pWindow->OnKeyRelease(keysym);
            };
            break;
        } case MapNotify: {
            pWindow->OnShow();
            break;
        } case UnmapNotify: {
            pWindow->OnHide();
            break;
        } case ClientMessage: {
            // If there is a 'WM_DELETE_WINDOW' message, return false.
            // It is necessary to break the event handling cycle and to close the application safely.
            // XInternAtom can generate BadAlloc and BadValue errors.
            ::Atom protocolsAtom = ::XInternAtom(m_pXServerConnection->Get(), "WM_PROTOCOLS", false);
            ::Atom deleteWindowAtom = ::XInternAtom(m_pXServerConnection->Get(), "WM_DELETE_WINDOW", false);
            if(Event.xclient.message_type == protocolsAtom && Event.xclient.data.l[0] == static_cast<long>(deleteWindowAtom)) {
                return false;
            }
            break;
        } default: {
            break;
        }
    }
    return true;
}

} // OOXlib
